package com.ucar.ui.main;



import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.LocationManagerProxy;
import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.CameraUpdateFactory;
import com.amap.api.maps2d.LocationSource;
import com.amap.api.maps2d.MapView;
import com.amap.api.maps2d.AMap.OnCameraChangeListener;
import com.amap.api.maps2d.model.BitmapDescriptorFactory;
import com.amap.api.maps2d.model.CameraPosition;
import com.amap.api.maps2d.model.LatLng;
import com.amap.api.maps2d.model.LatLngBounds;
import com.amap.api.maps2d.model.MyLocationStyle;
import com.amap.api.maps2d.UiSettings;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeAddress;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.GeocodeSearch.OnGeocodeSearchListener;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ucar.AppController;
import com.ucar.R;
import com.ucar.bean.AD;
import com.ucar.bean.Area;
import com.ucar.dialog.SelectAreaDialog;
import com.ucar.dialog.SelectAreaDialog.OnCallBack;
import com.ucar.net.BaseResponse;
import com.ucar.net.Callback;
import com.ucar.net.NetRequest;
import com.ucar.ui.base.BaseFragment;
import com.ucar.util.Utils;

import android.annotation.SuppressLint;
import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.TextView;

/**
 * 首页Fragment
 * @author moon
 *
 */
public class MainFragment extends BaseFragment implements
	LocationSource, AMapLocationListener, Runnable, OnGeocodeSearchListener,
	OnClickListener, OnCallBack
{
	private static final String TAG = MainFragment.class.getSimpleName();

	private static final int MESSAGE_MAP_CHANGE = 0x0001;
	
	private MapView mapView;
	private AMap aMap;
	private LocationManagerProxy mAMapLocManager = null;
	private OnLocationChangedListener mListener;
	private GeocodeSearch geocoderSearch;
	
	private LatLng latLng;
	private LatLngBounds bounds;
	
	private ViewGroup layoutLocation;
	private TextView tvStatus;
	private TextView tvAddress;
	
	private String addressName;
	
	private ArrayList<Area> areas = new ArrayList<Area>();
	
	private MainFragCallBack mCallBack;
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_main, container, false);
		return view;
	}
	
	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) 
	{
		super.onViewCreated(view, savedInstanceState);
		
		mapView.onCreate(savedInstanceState);// 此方法必须重写
	}

	@Override
	public void onInit() {
		
	}

	@Override
	public void onFindViews() {
		mapView = find( R.id.map );
		layoutLocation = find( R.id.layout_location );
		tvStatus = find( R.id.tv_status );
		tvAddress = find( R.id.tv_address );
	}

	@Override
	public void onInitViewData() {
		if (aMap == null) 
		{
			aMap = mapView.getMap();
			setUpMap();
		}
	}

	@Override
	public void onBindListener() 
	{
		aMap.setOnCameraChangeListener( new OnCameraChangeListener() {
			
			@Override
			public void onCameraChangeFinish(CameraPosition mCameraPosition ) 
			{
				LatLng center = aMap.getCameraPosition().target;
				latLng = new LatLng( center.latitude , center.longitude );
				bounds = aMap.getProjection().getVisibleRegion().latLngBounds;
				
				mMapHandler.sendEmptyMessage( MESSAGE_MAP_CHANGE );
			}
			
			@Override
			public void onCameraChange(CameraPosition mCameraPosition) 
			{
				tvStatus.setText( R.string.tv_locating );
			}
		});
		
		layoutLocation.setOnClickListener( this );
	}
	
	@Override
	public void onClick(View v) {
		switch ( v.getId() ) {
			case R.id.layout_location:
				if ( !mSpUtil.isLogin() )
				{
					AppController.getInstance().redirectLogin( mContext );
					return;
				}
				if ( areas.isEmpty() )
				{
				}
				else
				{
					new SelectAreaDialog( mContext, areas, this ).show();
				}
				break;
		}
	}
	
	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		mapView.onSaveInstanceState(outState);
	}
	
	@Override
	public void onResume() {
		super.onResume();
		mapView.onResume();
	}
	
	@Override
	public void onPause() {
		super.onPause();
		mapView.onPause();
		deactivate();
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		mapView.onDestroy();
	}
	
	public void setmCallBack(MainFragCallBack mCallBack) {
		this.mCallBack = mCallBack;
	}

	/**
	 * 往地图上添加一个marker
	 */
	private void setUpMap() 
	{
		// 自定义系统定位小蓝点
		MyLocationStyle myLocationStyle = new MyLocationStyle();
		myLocationStyle.myLocationIcon(BitmapDescriptorFactory
				.fromResource(R.drawable.location_marker ) );// 设置小蓝点的图标
		myLocationStyle.strokeColor( Color.TRANSPARENT );// 设置圆形的边框颜色
		myLocationStyle.radiusFillColor( Color.TRANSPARENT );// 设置圆形的填充颜色
		myLocationStyle.strokeWidth( 1.0f );// 设置圆形的边框粗细
		aMap.setMyLocationStyle( myLocationStyle );
		aMap.setLocationSource( this );// 设置定位监听
		aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位，false表示隐藏定位层并不可触发定位，默认是false

		// 隐藏缩放控件
		UiSettings uiSettings = aMap.getUiSettings();
		uiSettings.setZoomControlsEnabled( false );
		
		geocoderSearch = new GeocodeSearch( mContext );
		geocoderSearch.setOnGeocodeSearchListener( this );
	}

	@Override
	public void onLocationChanged(Location location) {
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onLocationChanged(AMapLocation aLocation) 
	{
		if (mListener != null && aLocation != null) 
		{
			mListener.onLocationChanged(aLocation);// 显示系统小蓝点
			aMap.moveCamera( CameraUpdateFactory.zoomTo( 16 ) );
			deactivate();
			// 请求广告
			reqAdvertList();
		}
	}

	@SuppressWarnings("deprecation")
	@Override
	public void activate(OnLocationChangedListener listener) 
	{
		mListener = listener;
		if (mAMapLocManager == null) 
		{
			mAMapLocManager = LocationManagerProxy.getInstance( mContext );
			/*
			 * mAMapLocManager.setGpsEnable(false);
			 * 1.0.2版本新增方法，设置true表示混合定位中包含gps定位，false表示纯网络定位，默认是true Location
			 * API定位采用GPS和网络混合定位方式
			 * ，第一个参数是定位provider，第二个参数时间最短是2000毫秒，第三个参数距离间隔单位是米，第四个参数是定位监听者
			 */
			if ( !Utils.isNetworkValid( mContext ) )
			{
				// API定位采用GPS定位方式，第一个参数是定位provider，第二个参数时间最短是2000毫秒，第三个参数距离间隔单位是米，第四个参数是定位监听者
				mAMapLocManager.requestLocationUpdates(
						LocationManagerProxy.GPS_PROVIDER, 2000, 10, this);
			}
			else
			{
				mAMapLocManager.requestLocationUpdates( 
						LocationManagerProxy.NETWORK_PROVIDER, 2000, 10, this );
			}
		}
	}

	@SuppressWarnings("deprecation")
	@Override
	public void deactivate() 
	{
		mListener = null;
		if (mAMapLocManager != null) 
		{
			mAMapLocManager.removeUpdates(this);
			mAMapLocManager.destory();
		}
		mAMapLocManager = null;
	}
	
	@SuppressLint("HandlerLeak")
	Handler mMapHandler = new Handler()
	{
		public void handleMessage(android.os.Message msg) 
		{
			switch ( msg.what ) 
			{
				case MESSAGE_MAP_CHANGE:
					removeCallbacks( MainFragment.this );
					postDelayed( MainFragment.this, 1000 );
					break;
			}
		};
	};

	@Override
	public void run() 
	{
		Log.d(TAG, "center-" + latLng + "-bounds" + bounds );
//		showToast( "center-" + latLng + "-bounds" + bounds );
		
		getAddress( new LatLonPoint( latLng.latitude, latLng.longitude ) );
		
		// 获得区域列表数据
		reqAreaList( latLng.latitude, latLng.longitude );
	}
	
	/**
	 * 响应逆地理编码
	 */
	public void getAddress(final LatLonPoint latLonPoint) {
		RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 200,
				GeocodeSearch.AMAP);// 第一个参数表示一个Latlng，第二参数表示范围多少米，第三个参数表示是火系坐标系还是GPS原生坐标系
		geocoderSearch.getFromLocationAsyn(query);// 设置同步逆地理编码请求
	}

	/**
	 * 地址转换成经纬度结果
	 */
	@Override
	public void onGeocodeSearched(GeocodeResult result, int rCode) {
		if (rCode == 0) {
			if (result != null && result.getGeocodeAddressList() != null
					&& result.getGeocodeAddressList().size() > 0) {
				GeocodeAddress address = result.getGeocodeAddressList().get(0);
				
				double lat = address.getLatLonPoint().getLatitude();
				double lon = address.getLatLonPoint().getLongitude();
				latLng = new LatLng( lat, lon );
				
				aMap.moveCamera( CameraUpdateFactory.changeLatLng( latLng ) );
				addressName = address.getFormatAddress();
				int i = addressName.indexOf( "市" );
				if ( i != -1 )
				{
					addressName = addressName.substring( i + 1 );
				}
			} else {
				showToast( "没有结果");
			}

		} else if (rCode == 27) {
			showToast( "没有网络");
		} else if (rCode == 32) {
			showToast( "key错误");
		} else {
			showToast( "其他错误：" + rCode );
		}
	}

	/**
	 * 经纬度转换成地址结果
	 */
	@Override
	public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
		tvStatus.setText( R.string.tv_cur_location );
		if (rCode == 0) {
			if (result != null && result.getRegeocodeAddress() != null
					&& result.getRegeocodeAddress().getFormatAddress() != null) {
				addressName = result.getRegeocodeAddress().getFormatAddress();
				int i = addressName.indexOf( "市" );
				if ( i != -1 )
				{
					addressName = addressName.substring( i + 1 );
				}
				Log.d( TAG, addressName );
				tvAddress.setText( addressName );
			} else {
				showToast( "没有结果");
			}
		} else if (rCode == 27) {
			showToast( "没有网络");
		} else if (rCode == 32) {
			showToast( "key错误");
		} else {
			showToast( "其他错误：" + rCode );
		}
	}
	
	/**
	 * 获得区域列表数据
	 * @param lat
	 * @param lng
	 */
	private void reqAreaList( final double lat, final double lng )
	{
		String tag = "tag_request_arealist";
		NetRequest.getInstance( mContext ).get(new Callback() {

			@Override
			public void onSuccess(BaseResponse response) 
			{
				areas.clear();
				List<Area> area = response.getListResponse( new TypeToken<List<Area>>(){} );
				if ( area != null && !area.isEmpty() )
				{
					areas.addAll(area);
				}
			}

			@Override
			public void onPreExecute() {}

			@Override
			public void onFinished() {}

			@Override
			public void onFailed(String msg) {
				showToast( msg );
			}

			@Override
			public Map<String, String> getParams() {
				Map<String, String> params = new HashMap<String, String>();
				params.put("url", "area/arealist");
				params.put("latitude", String.valueOf( lat ) );
				params.put("longitude", String.valueOf( lng ) );
				params.put("source", "ANDROID" );
				return params;
			}
		}, tag);
	}
	
	@Override
	public void onSelected(int position) 
	{
	}
	
	/**
	 * 请求广告
	 */
	private void reqAdvertList()
	{
		// Tag used to cancel the request
		String tag = "tag_request_advertlist";
		NetRequest.getInstance(mContext).get(new Callback() {

			@Override
			public void onSuccess(BaseResponse response) 
			{
				String json = response.getDataArrStr();
				Gson gson = new Gson();
				ArrayList<AD> ads = gson.fromJson( json, new TypeToken<List<AD>>(){}.getType() );
				// 显示广告
				if ( ads != null && !ads.isEmpty() )
				{
					AD ad = ads.get( 0 );
					if ( mCallBack != null )
					{
						mCallBack.showAd( ad );
					}
				}
			}

			@Override
			public void onPreExecute() {}

			@Override
			public void onFinished() {}

			@Override
			public void onFailed(String msg) 
			{
			}

			@Override
			public Map<String, String> getParams() {
				Map<String, String> params = new HashMap<String, String>();
				params.put("url", "app/advertlist");
				params.put("token", mSpUtil.getToken() );
				params.put("longitude", String.valueOf( latLng.longitude ) );
				params.put("latitude", String.valueOf( latLng.latitude ) );
				return params;
			}
		}, tag);
	}
	
	public interface MainFragCallBack
	{
		public void showAd( AD ad );
	}
}
